package com.sneaker.shower.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.sneaker.shower.common.BizException;
import com.sneaker.shower.common.ThreadLocalCache;
import com.sneaker.shower.entity.domain.order.CartDO;
import com.sneaker.shower.entity.domain.order.SubOrderDO;
import com.sneaker.shower.entity.dto.CartDTO;
import com.sneaker.shower.entity.dto.GoodsItemDTO;
import com.sneaker.shower.entity.dto.SubOrderDTO;
import com.sneaker.shower.entity.dto.UserDTO;
import com.sneaker.shower.entity.enums.SubOrderStatusEnum;
import com.sneaker.shower.mapper.CartMapper;
import com.sneaker.shower.mapstruct.CartMapStruct;
import com.sneaker.shower.mapstruct.SubOrderMapStruct;
import com.sneaker.shower.service.CartService;
import com.sneaker.shower.service.SubOrderService;
import lombok.extern.slf4j.Slf4j;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class CartServiceImpl extends ServiceImpl<CartMapper, CartDO> implements CartService {

    //todo 发布时需调大jvm内存
    private static final ExpiringMap<Long, CartDO> userCartMap =
            ExpiringMap.builder().expiration(7, TimeUnit.DAYS)
                    .expirationPolicy(ExpirationPolicy.CREATED).build();
    private final SubOrderService subOrderService;

    @Autowired
    @Lazy
    public CartServiceImpl(SubOrderService subOrderService) {
        this.subOrderService = subOrderService;

    }

    @Override
    public void add(List<GoodsItemDTO> goodsItemDTOList) {
        CartDO cartDO = getUserCart();
        // 产品记录入库，订单基础金额计算
        if (CollectionUtils.isEmpty(goodsItemDTOList)) {
            throw new BizException("当前订单未选择产品");
        }
        SubOrderDTO subOrderDTO = new SubOrderDTO();
        subOrderDTO.setGoodsItemDTOList(goodsItemDTOList);
        Boolean submit = subOrderService.submit(subOrderDTO, cartDO.getGuid(), Boolean.TRUE, SubOrderStatusEnum.WAIT_FOR_SUBMITTING.getCode(), goodsItemDTOList.get(0).getType());
        if (!submit) {
            throw new BizException("购物车添加失败，请稍候重试");
        }
    }

    @Override
    public Boolean remove(Long subOrderGuid) {
        return subOrderService.removeById(subOrderGuid);
    }

    @Override
    public CartDTO getCart() {
        CartDO userCartDO = getUserCart();
        CartDTO cartDTO = CartMapStruct.INSTANCE.do2DTO(userCartDO);
        List<SubOrderDO> list = subOrderService.list(new LambdaQueryWrapper<SubOrderDO>()
                .eq(SubOrderDO::getCartGuid, cartDTO.getGuid()));
        List<SubOrderDTO> subOrderDTOS = SubOrderMapStruct.INSTANCE.doList2DTOList(list);
        cartDTO.setSubOrderDTOS(CollectionUtils.isEmpty(subOrderDTOS) ? Lists.newArrayList() : subOrderDTOS);
        return cartDTO;
    }

    @Override
    public void removeAll() {
        CartDO userCartDO = getUserCart();
        subOrderService.remove(new LambdaQueryWrapper<SubOrderDO>().eq(SubOrderDO::getCartGuid, userCartDO.getGuid()));
    }

    public Integer getCount() {
        return subOrderService.count(new LambdaQueryWrapper<SubOrderDO>().eq(SubOrderDO::getUserGuid, Long.parseLong(ThreadLocalCache.get().getGuid())).eq(SubOrderDO::getIsInCart, true));
    }

    private CartDO getUserCart() {
//        UserDTO userDTO = new UserDTO();
//        userDTO.setOrganizationGuid(999999999998L);
//        userDTO.setGuid(999999999999L + "");
        UserDTO userDTO = ThreadLocalCache.get();
        if (userDTO == null) {
            throw new BizException("非法请求，无用户信息");
        }
        CartDO cartDO = userCartMap.get(Long.parseLong(userDTO.getGuid()));
        if (cartDO != null) {
            return cartDO;
        }
        cartDO = getOne(new LambdaQueryWrapper<CartDO>().eq(CartDO::getUserGuid, userDTO.getGuid()));
        if (ObjectUtils.isEmpty(cartDO)) {
            cartDO = new CartDO();
            cartDO.setGuid(IdWorker.getId());
            cartDO.setOrganizationGuid(Long.parseLong(userDTO.getOrganizationGuid()));
            cartDO.setUserGuid(Long.valueOf(userDTO.getGuid()));
            save(cartDO);
        }
        userCartMap.put(Long.valueOf(userDTO.getGuid()), cartDO);
        return cartDO;
    }

}
